package com.insight.config.shiro.filters;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import com.insight.common.constant.CommonConstant;
import com.insight.config.shiro.token.JwtToken;
import com.insight.config.shiro.utils.ShiroUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * @Description: 鉴权登录拦截器
 * @Author: Scott
 * @Date: 2018/10/7
 **/
@Slf4j
public class JwtFilter extends BasicHttpAuthenticationFilter {

    private boolean allowOrigin = true;

    public JwtFilter() {
    }

    public JwtFilter(boolean allowOrigin) {
        this.allowOrigin = allowOrigin;
    }

    /**
     * 执行登录认证
     *
     * @param request
     * @param response
     * @param mappedValue
     * @return
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        try {
            if (log.isDebugEnabled() && request != null) {
                log.debug(ShiroUtils.getRequestUri(request));
            }
            boolean b = executeLogin(request, response);
            if (!b) {
                return false;
            }
            return true;
        } catch (Exception e) {
            String uri = request != null ? ShiroUtils.getRequestUri(request) : "unknown";
            throw new AuthenticationException(String.format("Token失效，请重新登录。%s", uri), e);
        }
    }

    /**
     *
     */
    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String token = httpServletRequest.getHeader(CommonConstant.X_ACCESS_TOKEN);

        JwtToken jwtToken = new JwtToken(token);
        // 提交给realm进行登入，如果错误他会抛出异常并被捕获
        getSubject(request, response).login(jwtToken);
        // 如果没有抛出异常则代表登入成功，返回true
        return true;
    }

    /**
     * 对跨域提供支持
     */
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) {
        try {
            if (ShiroUtils.extracted(request, response, allowOrigin)) {
                return false;
            }
            return super.preHandle(request, response);
        } catch (Exception e) {
            log.error("preHandle 执行过程中发生异常", e);
            return false;
        }
    }
}
